import java.awt.BorderLayout;
import java.awt.Canvas;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.FocusEvent;
import java.awt.event.FocusListener;

import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JSpinner;
import javax.swing.Timer;
import javax.swing.colorchooser.ColorSelectionModel;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;

public class ballsJFrame extends JFrame implements ChangeListener {

    private JSpinner spinner;//微调按钮
    private ballsCanvas canvas;//用画布画球

    public ballsJFrame() {
        super("弹弹球");
        setBounds(300, 200, 400, 300);
        setDefaultCloseOperation(EXIT_ON_CLOSE);
        Color colors[] = {Color.red, Color.yellow, Color.BLUE, Color.green, Color.gray};//小球颜色及个数

        canvas = new ballsCanvas(colors, 100);//new一个画布
        getContentPane().add(canvas);

        JPanel panel = new JPanel();
        getContentPane().add(panel, BorderLayout.SOUTH);//getContentPane().add(panel,"SOUTH");
        panel.add(new JLabel("dalay"));
        spinner = new JSpinner();//new一个微调按钮
        spinner.setValue(100);//设置初始值new ballsCanvas(colors, 100);
        panel.add(spinner);
        spinner.addChangeListener(this);//监听里面的数值发生变化

        setVisible(true);
    }

    public static void main(String[] args) {

        new ballsJFrame();
    }

    public void stateChanged(ChangeEvent e) {

        int delay = Integer.parseInt("" + spinner.getValue());//获取微调按钮文本里的值
        canvas.setDelay(delay);//对timer设置数值
    }

}

class ballsCanvas extends Canvas implements ActionListener, FocusListener {

    private ball balls[];//球
    private Timer timer;//定时器

    class ball {//内部类，，底下画球时就可以直接调用坐标，不用getX（）函数
        private int x, y;
        private Color color;
        boolean up, left;//初始值是false

        public ball(int x, int y, Color color) {
            this.x = x;
            this.y = y;
            this.color = color;
        }

    }

    public ballsCanvas(Color[] colors, int delay) {
        this.balls = new ball[colors.length];
        for (int i = 0, x = 40; i < colors.length; i++, x += 40) {
            balls[i] = new ball(x, x, colors[i]);
        }

        this.addFocusListener(this);//监听焦点
        timer = new Timer(delay, this);//用法和btn.addActionLis一样
        timer.start();//定时器本身是一个线程对象，必须要启动才会生效
    }

    public void setDelay(int delay) {//在ballsJFrame 类中的方法进行设置数值
        timer.setDelay(delay);
    }

    public void paint(Graphics g) {//画笔
        for (int i = 0; i < balls.length; i++) {
            g.setColor(balls[i].color);//用当前颜色画球
            //方法1：
            balls[i].x = balls[i].left ? balls[i].x - 5 : balls[i].x + 5;
            //遇到边界就改变方向
            if (balls[i].x <= 0 || balls[i].x + 20 >= this.getWidth()) {//balls[i].x+20和balls[i].y+20因为球的坐标是 **球外接正方形左上方的那一点**，所以判断球碰到下面和右边的边界时要加上求的直径g.fillOval(balls[i].x, balls[i].y, 20, 20);
                balls[i].left = !balls[i].left;
            }
            balls[i].y = balls[i].up ? balls[i].y - 5 : balls[i].y + 5;
            if (balls[i].y <= 0 || balls[i].y + 20 >= this.getHeight()) {
                balls[i].up = !balls[i].up;
            }
            //方法2：
// balls[i].x+=5;//球被画死了
// balls[i].y+=5;
            g.fillOval(balls[i].x, balls[i].y, 20, 20);//画实心球，直径20,20
        }
    }

    public void actionPerformed(ActionEvent e) {//监听线程,每delay时间间隔画一次球

        repaint();
    }

    public void focusGained(FocusEvent e) {//监听焦点，点击画布时停止

        timer.stop();
    }

    public void focusLost(FocusEvent e) {//监听焦点，点击其他重新启动，如微调按钮编辑框

        timer.restart();
    }
}

